<?php

class ExceptionHandler implements IExceptionHandler {
	const DISPLAY = "display" ;
	const REDIRECT = "redirect" ;
	/**
	 * Object instance keeper
	 *
	 * @var SessionHandler
	 */
	private static $oInstance = null;

	/**
	 * Singleton
	 *
	 * @return SessionHandler
	 */
	public static function getDefault(){
		if( self::$oInstance == null ){
			self::$oInstance = new ExceptionHandler();
		}
		return self::$oInstance;
	}

	private function __construct(){
		set_exception_handler( array( $this, "displayException" ) );
	}

	public function displayException( $exception ){

		// TODO:  Wprowadzić lepsze wyświetlanie błędów z wyróżnieniem ErrorExceptiona

		if( $exception instanceof ArrowMessageException ) {
			$msg = unserialize( $exception->getMessage() );
			if( ArrowRouter::getDefault()->getCallType() == ArrowRouter::REMOTE_CALL ) {
				ArrowLogger::log( $msg["msg"] , ArrowLogger::EL_ERROR  );
				echo $msg["msg"]  ;
				exit;
			} else {
				echo "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\"><html xmlns=\"http://www.w3.org/1999/xhtml\"><head>	<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" /></head><body><h3>{$msg["msg"]}</h3></body></html>" ;
				return;
			}
		}
		
			

		require_once( ARROW_LIBS_PATH."/krumo/krumo.php" );
		error_reporting(0);
		try {
			$prmsg = @$exception->getMessage() ;
			try {
				$prmsg = print_r( unserialize( $prmsg ), 1 );
			}catch( Exception $e ) {}
			$errstr = <<<ERRSTR
<div style="display:none;" >
------------------------------------------------------------------------------------------------------------------------
*************************************************************************************************************************			
			
			$prmsg

*************************************************************************************************************************
</div>
ERRSTR;

			$errstr .= $this->buildExString( $exception ) ;
			try{
				ArrowLogger::log( $errstr, ArrowLogger::EL_ERROR  );
			} catch( Exception $e ) {}
			
			try {
				$mime_boundary = "----Arrow----".md5(time());
				$headers = "From: ArrowSerwis\n";
				$headers .= "Reply-To: ArrowSerwis\n";
				$headers .= "MIME-Version: 1.0\n";
				$headers .= "Content-Type: multipart/alternative; boundary=\"$mime_boundary\"\n";
				$message = "--$mime_boundary\n";
				$message .= "Content-Type: text/html; charset=UTF-8\n";
				$message .= "Content-Transfer-Encoding: 8bit\n\n";
				$message .= str_replace( array("none", "style=\"background-color:rgb(244, 245, 238);\"", "<table" ) , array("","","<table border=\"1\" ") ,$errstr ) ;
				$ermail = trim( ArrowSettings::getDefault()->getSetting("arrow.error_mail") );
				if( !empty($ermail) ) @mail( $ermail, "[Arrow - {$_SERVER["HTTP_HOST"]}]Wystapil blad w serwisie.", $message, $headers ) ;

			} catch(Exception $e) {
				exit("Can't send email ");
			}
				
			if( ArrowController::getDefault()->getProject()->getErrorOnError() == self::DISPLAY ) {
				if( ArrowRouter::getDefault()->getCallType() == ArrowRouter::REMOTE_CALL || ArrowRouter::getDefault()->getCallType() == ArrowRouter::TEMPLATE_METHOD_CALL) {
					$returnArray = array();
						
					$message = @$exception->getMessage() ;
					$aret = "" ;
					try {
						$message = unserialize( $message );
					}catch( Exception $e ) {}
						
					$returnArray[ "arrowerr" ] = $message;
					$returnArray[ "file" ] = @$exception->getFile();
					$returnArray[ "line" ] = @$exception->getLine();

					$remoteResponse = ArrowController::getDefault()->getProject()->getHandler( ArrowProject::IRemoteResponseHandler );
					$remoteResponse->setHeaders();
					$response = $remoteResponse->getResponse( $returnArray );
					exit( $response );
				} else {
					@ob_clean() ;
					$user = Auth::getDefault()->getUser() ;
						
					if( !isset( $_SESSION["DEBUG"] ) && ( $user == null || !$user->isInGroup("!!!DEV!!!") ) ) {
						$date = date("Y-m-d H:i:s");
						$errstr = <<<MSG
<h1>Internal Server Error</h1>
An internal error occurred while the Web server was processing your request.<br /> 
Please contact the webmaster to report this problem. <br />
Thank you.
<hr />
						$date
MSG;

					}
					print $this->getHead().$errstr.$this->getFooter() ;
					exit();
				}
			} else {  // REDIRECT

				$template_redirect_name = ArrowRouter::getDefault()->getTemplate()->getContainer()->geterrorTemplate() ;
				if(  strpos( $template_redirect_name, "::" ) > 0 )
				ArrowController::redirectToTemplate( $template_redirect_name ) ;
				else {
					ArrowController::getDefault()->redirectToStaticAddress( $template_redirect_name ) ;
				}
			}
		}
		catch( Exception $e ) {
			print_r( "Błąd w procedurze obsługi błędów \n<pre>".print_r($e,true) );
			exit;
		}
	}

	/**
	 * Change excetption to sring to show
	 * @param $exception
	 * @return unknown_type
	 */
	private function buildExString( $exception ) {
			
		$br = "\n" ;
		$ret = "" ;
		$ret .= $this->buildHeaderEx( $exception );
		$ret .= "<fieldset>";
		$ret .= "<legend>[Stack Trace]</legend>\n" ;
		$ret .= "<div style=\"white-space:pre;margin-left:20px;\" >".$exception->getTraceAsString()."</div>";
		$ret .= "</fieldset>";
		$ret .= "<fieldset>";
		$ret .= "<legend>[Input Data]</legend>\n" ;
		$ret .= "<div style=\"margin-left:20px;\" >".$this->getInputString()."</div>";
		$ret .= "</fieldset>";
		$ret .= "<fieldset>";
		$ret .= "<legend>[Session Data]</legend>\n" ;
		$ret .= "<div style=\"margin-left:20px;\" >".$this->getSessionString()."</div>";
		$ret .= "</fieldset>";
		$ret .= "<fieldset>";
		$ret .= "<legend>[Stack Trace - long]</legend>\n" ;
		if( isset($_GET["trace"]) ) {
			krumo::backtrace();
			$ret .= "<div style=\"\" >".ob_get_contents()/*$this->tableToString( "StackTrace" , $exception->getTrace()  )*/."</div>";
		} else {
			$ret .= "<a href=\"javascript:window.location.href += '&trace=1'; \" >Uruchom</a>" ;
		}
		$ret .= "</fieldset>";//.print_r($exception->getTrace(),1) ;
		return $ret;
	}

	private function getInputString() {
		ob_start();
		if( !empty($_FILES) )
		krumo($_GET,$_POST, $_FILES, $_COOKIES);
		else
		krumo($_GET,$_POST, $_FILES, $_COOKIES);
		$cont = ob_get_contents();
		ob_end_clean();
		return $cont;
	}

	private function getSessionString() {
		ob_start();
		krumo($_SESSION);
		$cont = ob_get_contents();
		ob_end_clean();
		return $cont;
	}


	private function buildHeaderEx( $exception ) {
		$br = "\n" ;

		$ret = "<h1>Internal Server Error</h1>";

		$message = $exception->getMessage() ;
		$aret = "" ;
		try {
			$umessage = unserialize( $message );
			if(isset($umessage["msg"])){
				$message =  $umessage["msg"];
				unset($umessage["msg"]);
			} else $message = "--unknown--" ;
			if(!empty($umessage)){
				ob_start();
				krumo($umessage);
				$aret = ob_get_contents();
				ob_end_clean();
			}
				
		}catch( Exception $e ) {}

		$ret.= "<h2>{$message}</h2>".$aret;

		/*if( strpos( $message, ":" ) > 0 ) {
			$message = unserialize( $message );
			if(isset($message["msg"])){
			$ret.= "<h2>{$message["msg"]}</h2>";
			unset($message["msg"]);
			}
			if(!empty($message)){
			ob_start();
			krumo($message);
			$ret.= ob_get_contents();
			ob_end_clean();
			}
			}else{
			$ret.= "<h2>{$message}</h2>";
			}*/


		$line = 0 ;
		$line = $exception->getLine()-1 ;
		$pathfile = $exception->getFile() ;
		$arr_file = file($pathfile) ;
		$str = "";
		for( $i = $line - 5 ; $i < $line + 5; ++$i ){
			$tmp = str_replace(array("\t", " "), array("&nbsp;&nbsp;&nbsp;&nbsp;", "&nbsp;"), htmlentities($arr_file[$i]));
			if($i == $line)
			$str .= "<span style=\"color: red;\">$i ".$tmp."</span><br />";
			else{
				$str .= "$i ".$tmp."<br />";
			}
			 
			 
		}

		$ret .= "<fieldset><legend>Exception data:</legend><b>Line:</b> {$line}; <b>Code:</b> {$exception->getCode()}; <b>Time:</b> ".date("l jS F Y h:i:s A")."</fieldset>";
		$ret .= "<fieldset><legend>Exception file:</legend><b>".$pathfile."</b><br /> $str</fieldset>";

		 
		return $ret ;
	}

	private function getHead() {
		$head =
<<<HEAD
	<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="pl" lang="pl">
<head>
   	<title>Arrow Error</title>
   	<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
   	<style type="text/css" >
   	body {
   		background-color: white;
   		font-size:12px;
   		font-family:"Verdana";
	}
	
	h1{
		color:red;
		font-size:18pt;
		font-weight:normal;
	}
	
	h2{
		color:maroon;
		font-family:"Verdana";
		font-size:14pt;
		font-weight:normal;
	}
	
	legend{
		font-size: 14px;
		color:maroon;
		font-weight: bold;
		padding: 4px;
	}
	
	.krumo-footnote{
		display: none;
	}
	
	
   	</style>
</head><body>
HEAD;
		return $head;
	}

	private function getFooter() {
		$footer = "</body></html>" ;
		return $footer;
	}
}

?>